import React from 'react'
import PropTypes from 'prop-types'
import styles from './WxChat.less'
import {queryArray, toEmotion} from 'utils'
import {Button, message, Spin} from 'antd'
import {connect} from 'dva'
import Modal from './Modal'
import {findList} from "services/message"

const transferData = item => ({
  direction: item.msgDirection ? 1 : 2,
  id: item.id,
  type: item.msgCategory,
  content: item.chatContent,
  media: item.mediaPath,
  ctime: item.chatTime,
})

class WxChat extends React.Component {

  constructor (props) {
    super(props)
    this.state = {
      isUpperLaoding: false,
      isUnderLaoding: false,

      isRefreshedAll: false,
      isLoadedAll: false,

      minHeight: 700,
      dataArray: [],

      topLoading: false,
      bottonLoading: false,
      stopTopLoading: false, //是否停止传播滚动到顶部事件
      stopBottonLoading: false,  //是否停止传播滚动到底部事件
      visible: false,

      loading: true,

      defaultOwnerAvatar: '/public/a/' + (parseInt(Math.random() * 15, 10) + 1) + '.jpg',
      defaultContactAvatar: '/public/a/' + (parseInt(Math.random() * 15, 10) + 1) + '.jpg',

      upperTimes: 0,
      underTimes: 0,
      upperId: 0,
      underId: 6,
    }
  }

  static propTypes = {
    contactNickname: PropTypes.string,  // 微信主人昵称
    width: PropTypes.number,            // 组件宽度，默认450
    wrapBg: PropTypes.string,           // 外层父元素背景颜色，默认#efefef
    maxHeight: PropTypes.number,        // 展示窗口最高高度, 默认900
    contactAvatarUrl: PropTypes.string, // 好友头像url
    ownerAvatarUrl: PropTypes.string,   // 微信主人头像url
    ownerNickname: PropTypes.string,    // 微信主人昵称
    // getUpperData: PropTypes.func.isRequired,  // （必需）当滚动到上方时加载数据的方法，返回值要为Promise对象，resolve的结构同data
    // getUnderData: PropTypes.func.isRequired,  // （必需）当滚动到下方时加载数据的方法，返回值同上
    // data: PropTypes.array.isRequired,         // （必需）传入初始化数据， 结构如下：
  }

  static defaultProps = {
    width: 450,
    wrapBg: '#efefef',
    maxHeight: 700,
  }

  getUpperData () {
    let target = this
    const {upperId, upperTimes} = this.state
    return new Promise(function (resolve) {
      resolve([])

      target.setState({
        upperId: upperId + 2,
        upperTimes: upperTimes + 1,
      })
    })
  }

  getUnderData () {
    const {message: {pagination, cwxId, owxId, chatTime}, dispatch} = this.props
    console.log(this.props)
    const {underId, underTimes} = this.state
    let target = this
    return new Promise(function (resolve) {
      findList({
        current: Number(pagination.current) + 1,
        cwxId: cwxId,
        owxId: owxId,
        chatTime: chatTime,
      }).then(res => {
        if (res.code === 0 && res.data.records.length > 0) {
          dispatch({
            type: 'message/updatePagination',
            payload: {
              pagination: {
                ...pagination,
                current: Number(pagination.current) + 1,
              },
            },
          })
          resolve(res.data.records)
        } else {
          resolve([])
        }
      })

      target.setState({
        underId: underId + 2,
        underTimes: underTimes + 1,
      })
    })
  }

  componentDidMount () {
    this.initData()
    const minHeight = document.getElementById('window-view-container').offsetHeight
    const maxHeight = document.getElementById('window-view-container').offsetHeight
    this.setState({
      minHeight,
      maxHeight,
    })
  }

  componentWillReceiveProps (nextProps) {
    const {message: {list = []}} = nextProps
    const {dataArray} = this.state

    const newData = this.getNewDataList(list)

    this.setState({
      dataArray: dataArray.concat(newData.map(transferData)),
      loading: false,
    })
  }

  getNewDataList (list) {
    const {dataArray} = this.state

    return list.filter(_ => {
      const exists = dataArray.filter(i => i['id'] === _.id)
      return exists.length === 0
    })
  }

  initData () {
    const {message: {list = []}} = this.props
    const {dataArray} = this.state
    const target = this
    setTimeout(() => {
      target.setState({loading: false})
    }, 5000)

    this.setState({
      dataArray: dataArray.concat(list.map(transferData)),
    })
  }

  realMinHeight () {
    return this.state.minHeight + 30
  }

  updateState (payload) {
    this.setState(payload)
  }

  // 向上拉刷新
  refresh (done) {
    const {isUpperLaoding, isRefreshedAll, dataArray} = this.state
    if (isUpperLaoding) {
      return
    }

    if (isRefreshedAll) {
      done(true)
      this.setState({isUpperLaoding: false})
      return
    }

    const updateState = (payload) => {
      this.setState({...payload})
    }

    try {
      this.getUpperData().then(function (data) {
        if (data.length === 0) {
          updateState({isRefreshedAll: true})
          done(true)
        } else {
          // 倒序合并
          updateState({dataArray: data.reverse().concat(dataArray)})
          done()
        }
      })
    } catch (error) {
      console.error('wxChat: props "getUpperData" must return a promise object!')
    }
    this.setState({isUpperLaoding: false})
  }

  //向下拉加载
  infinite (done) {
    const {isUnderLaoding, isLoadedAll, dataArray} = this.state
    const target = this
    if (isUnderLaoding) {
      return
    }
    if (isLoadedAll) {
      done(true)
      this.setState({isUnderLaoding: false})
      return
    }

    const updateState = (payload) => {
      this.setState({...payload})
    }

    try {
      this.getUnderData().then(function (data) {
        const newDataList = target.getNewDataList(data)
        if (newDataList && newDataList.length === 0) {
          updateState({isLoadedAll: true})
          done(true)
        } else {
          done()
          const newDataArray = dataArray.concat(newDataList.map(transferData))
          // 直接合并
          updateState({dataArray: newDataArray})
        }
      })
    } catch (error) {
      console.error('wxChat: props "getUnderData" must return a promise object!')
    }
    this.setState({isUnderLaoding: false})
  }


  parseXml = (text) => new DOMParser().parseFromString(text, "text/xml")

  getTextOfXml = (content, field) => {
    const xmlDoc = this.parseXml(content)
    return xmlDoc.getElementsByTagName(field)[0].childNodes[0].nodeValue
  }

  getTransferMsg = (content) => {
    return '[收取] ' + this.getTextOfXml(content, "feedesc")
  }

  getAlertTitle = (content) => {
    return this.getTextOfXml(content, "title")
  }

  getAlertDesc = (content) => {
    return this.getTextOfXml(content, "des")
  }

  showModal = () => {
    const {dispatch} = this.props
    dispatch({
      type: "employee/query",
      payload: {current: 1, size: 10},
    })
    dispatch({
      type: "employee/updateState",
      payload: {
        modalVisible: true,
      },
    })
  }

  render () {
    const {dataArray, topLoading, bottonLoading, stopTopLoading, loading, stopBottonLoading, defaultOwnerAvatar, defaultContactAvatar} = this.state
    const {
      message: {
        recommended,
        ownerAvatarUrl: oicon,
        contactAvatarUrl: cicon,
        contactNickname,
      },
      wrapBg,
      maxHeight,
      width,
      dispatch,
      modal = false,
      employee,
    } = this.props
    const {
      list, departments, roles, pagination, currentItem, modalVisible, disable, modalType, selectedRowKeys, selectedRows,
    } = employee

    const modalProps = {
      visible: modalVisible,
      title: '优质聊天记录',
      list,
      departments,
      roles,
      pagination,
      onChange (page) {
        dispatch({
          type: "employee/query",
          payload: {
            current: page.current,
            size: page.pageSize,
          },
        })
      },
      handleSearch (data) {
        if (data) {
          dispatch({
            type: "employee/query",
            payload: {
              ...data,
              current: 1,
              size: 10,
            },
          })
        } else {
          dispatch({
            type: "employee/query",
          })
        }
      },
      showModal: this.showModal,
      handleCancel () {
        dispatch({
          type: "employee/updateState",
          payload: {
            modalVisible: false,
            selectedRowKeys: [],
          },
        })
      },
      rowSelection: {
        selectedRowKeys,
        onChange: (keys, selectedRows) => {
          dispatch({
            type: 'employee/updateState',
            payload: {
              selectedRowKeys: keys,
              selectedRows: selectedRows,
            },
          })
        },
      },
      handleOk (description) {
        let data = {
          highQualityChatRecord: {
            personalChatRecords: {
              id: null,
            },
          },
        }
        if (description) {
          data.highQualityChatRecord["description"] = description
        }

        let {id} = dataArray[0]
        data.highQualityChatRecord.personalChatRecords.id = Number(id)
        data.viewerId = selectedRows.map(item => Number(item.id))
        if (selectedRows.length <= 0) {
          message.warn("请至少选择一位员工查看权限")
          return
        }
        // data.highQualityChatRecordId = 1    //优质聊天记录ID 前端先写在代码里
        dispatch({
          type: 'highQualityChatRecord/create',
          payload: data,
        }).then(() => {
          dispatch({
            type: "employee/updateState",
            payload: {
              modalVisible: false,
              selectedRowKeys: [],
              selectedRows: [],
            },
          })
        })
      },
    }

    const ownerAvatarUrl = oicon ? oicon : defaultOwnerAvatar
    const contactAvatarUrl = cicon ? cicon : defaultContactAvatar

    const topDone = (stopTopLoading) => {
      this.setState({topLoading: false})
      if (stopTopLoading)
        this.setState({stopTopLoading: true})
    }

    const bottonDone = (stopBottonLoading) => {
      this.setState({bottonLoading: false})
      if (stopBottonLoading)
        this.setState({stopBottonLoading: true})
    }

    const onScroll = () => {
      const container = document.getElementById('window-view-container')

      if (container.scrollTop <= 0 && !stopTopLoading) {
        if (topLoading) return

        this.setState({topLoading: true})
        container.scrollTop -= 40
        this.refresh(topDone)
      }
      if ((container.offsetHeight + container.scrollTop + 1 >= container.scrollHeight) && !stopBottonLoading) {
        if (bottonLoading) return

        this.setState({bottonLoading: true})
        container.scrollTop += 40
        this.infinite(bottonDone)
      }
    }

    const getMsgContent = (msg) => {
      if (msg.type === 1 || msg.type === 47) {
        return (
          <div className={styles.text} dangerouslySetInnerHTML={{__html: toEmotion(msg.content)}}/>
        )
      } else if (msg.type === 3 || msg.type === 1048625) {
        return (
          <div className={styles.text}>
            <img src={msg.media} className={styles.image} alt="聊天图片"/>
          </div>
        )
      } else if (msg.type === 419430449111 || msg.type === 419430449) {
        return (
          <div className={styles.text + ' ' + styles.money}>
            <div style={{verticalAlign: 'middle'}}>
              <img src="/public/transfer.png" width="30" height="30" style={{marginRight: 10}}/>
              <span className={styles.iconText}>{this.getTransferMsg(msg.content)}</span>
            </div>
            <div className={styles.moneyFooter}>微信转账</div>
          </div>
        )
      } else if (msg.type === 436207665) {
        return (
          <div className={styles.text + ' ' + styles.money}>
            <div style={{verticalAlign: 'middle'}}>
              <span className={styles.iconText}>
                <img src="/public/hongbao.png" width="30" height="30" style={{marginRight: 8}}/>
                恭喜发财，大吉大利
              </span>
            </div>
            <div className={styles.moneyFooter}>微信红包</div>
          </div>
        )
      } else if (msg.type === 285212721) {
        // 公众号消息
        return (
          <div className={styles.text} dangerouslySetInnerHTML={{__html: '公众号消息'}}/>
        )
      } else if (msg.type === 49) {
        // 分享文件
        return (
          <div className={styles.text} dangerouslySetInnerHTML={{__html: '分享文件'}}/>
        )
      } else if (msg.type === 42) {
        // 分享名片
        return (
          <div className={styles.text} dangerouslySetInnerHTML={{__html: '分享名片'}}/>
        )
      } else if (msg.type === 34) {
        // 语音消息
        return (
          <div className={styles.text} dangerouslySetInnerHTML={{__html: '语音消息'}}/>
        )
      } else if (msg.type === 50) {
        // 视频/音频通话
        return (
          <div className={styles.text} dangerouslySetInnerHTML={{__html: '语音/视频通话'}}/>
        )
      } else if (msg.type === 48) {
        // 位置分享
        return (
          <div className={styles.text} dangerouslySetInnerHTML={{__html: '位置分享'}}/>
        )
      }

      return undefined
    }

    const getMsgCard = (msg) => {
      if (msg.type === 10000 || msg.type === 570425393) {
        return (
          <p className={styles.time + " " + styles.system}><span dangerouslySetInnerHTML={{__html: msg.content}}/></p>)
      } else if (msg.type === 318767153) {
        // 公众号提示消息
        return (<p className={styles.alert}>
          <span className={styles.title}>{this.getAlertTitle(msg.content)}</span>
          <span className={styles.time}>{new Date(msg.ctime).format('MM月dd日')}</span>
          <p className={styles.content}>{this.getAlertDesc(msg.content)}</p>
          <div className={styles.line}/>
          <span className={styles["link-text"]}>详情</span>
        </p>)
      }

      const msgContent = getMsgContent(msg)
      if (msgContent) {
        return (
          <div className={msg.direction === 1 ? styles.self : ''}>
            <img className={styles.avatar} width="45" height="45"
                 src={msg.direction === 1 ? ownerAvatarUrl : contactAvatarUrl}/>
            {msgContent}
          </div>
        )
      }
      return (
        <p className={styles.time + " " + styles.system}>
          <span>
            {'[暂未支持的消息类型:' + msg.type + ']\n\r' + msg.content}
          </span>
        </p>
      )
    }

    const toMessageList = () => {
      return dataArray.map((msg, index) => (
        <li key={msg.id}
            className={styles[msg.direction === 1 ? 'an-move-right' : 'an-move-left']}>
          <p className={styles.time}><span>{msg.ctime}</span></p>
          {getMsgCard(msg, index)}
        </li>
      ))
    }

    return (
      <div className={styles[modal ? 'wxchat-container-center' : 'wxchat-container']} onScroll={onScroll}
           style={{backgroundColor: wrapBg, height: maxHeight + 'px', width: width + 'px'}}>
        <div className={styles.window} id="window-view-container">
          {
            dataArray && dataArray.length > 0 &&
            <div style={{
              float: "right",
              position: "absolute",
              zIndex: 102,
              right: 10,
              top: contactNickname ? '9%' : '2%',
            }}>
              <Button disabled={recommended} type={'primary'} size={'small'}
                      onClick={this.showModal}>{recommended ? '已推荐' : '推荐'}</Button>
            </div>
          }
          {
            dataArray && dataArray.length === 0 &&
            <div className={styles.loading}>
              <div style={{marginTop: '300px', textAlign: 'center', fontSize: '16px'}}>
                {loading ? <Spin/> : <span>未查找到聊天记录</span>}
              </div>
            </div>
          }

          {
            dataArray && dataArray.length > 0 && contactNickname &&
            <div className={styles.title}>
              <p>{contactNickname}</p>
            </div>
          }

          {
            dataArray && dataArray.length > 0 &&
            <div id="scrollLoader-container" className={styles.containerMain}>
              {
                topLoading &&
                <div className={styles.loading}>
                  <div className={styles.loader}>加载中...</div>
                </div>
              }

              <div style={{minHeight: this.realMinHeight() + 'px', overflowX: 'hidden'}}>
                <div className={styles.message}>
                  <ul style={{padding: 0}} id="message_list">
                    {toMessageList()}
                  </ul>
                </div>
              </div>

              {
                bottonLoading &&
                <div className={styles.loading}>
                  <div className={styles.loader}>加载中...</div>
                </div>
              }
            </div>
          }
        </div>
        <Modal {...modalProps}/>
      </div>
    )
  }
}

export default connect(({employee, message, loading}) => ({employee, message, loading}))(WxChat)
